import * as React from "react";
import { zhCN } from "date-fns/locale";
import dayjs from "dayjs";
import { useEffect, useId, useRef, useState } from "react";
import { CalendarDays } from "lucide-react";
import { Input } from "@/components/ui/input";

import { format, isValid, parse } from "date-fns";
import {
  DayPicker,
  DayPickerProps,
  getDefaultClassNames,
} from "react-day-picker";
import "react-day-picker/style.css";

interface PropsI extends Omit<DayPickerProps, "children"> {
  placeholder?: string;
  className?: string;
  value: Date | undefined;
  onChange: (value: Date) => void;
}

export const CustomDatePicker: React.FC<PropsI> = (
  {
    placeholder = "yyyy-MM-dd",
    className = "",
    value,
    onChange,
    ...dayPickerProps
  }: PropsI,
  ref: React.ForwardedRef<HTMLDivElement>
) => {
  const defaultClassNames = getDefaultClassNames();

  const dialogRef = useRef<HTMLDialogElement>(null);
  const dialogId = useId();
  const headerId = useId();

  // Hold the month in state to control the calendar when the input changes
  const [month, setMonth] = useState(
    value ? dayjs(value).toDate() : new Date()
  );

  // Hold the selected date in state
  const [selectedDate, setSelectedDate] = useState<Date | undefined>(value);

  // Hold the input value in state
  const [inputValue, setInputValue] = useState(
    dayjs(value).format("YYYY-MM-DD")
  );

  // Hold the dialog visibility in state
  const [isDialogOpen, setIsDialogOpen] = useState(false);

  // Function to toggle the dialog visibility
  const toggleDialog = () => setIsDialogOpen(!isDialogOpen);

  // Hook to handle the body scroll behavior and focus trapping.
  useEffect(() => {
    const handleBodyScroll = (isOpen: boolean) => {
      document.body.style.overflow = isOpen ? "hidden" : "";
    };
    if (!dialogRef.current) return;
    if (isDialogOpen) {
      handleBodyScroll(true);
      dialogRef.current.showModal();
    } else {
      handleBodyScroll(false);
      dialogRef.current.close();
    }
    return () => {
      handleBodyScroll(false);
    };
  }, [isDialogOpen]);

  const handleDayPickerSelect = (date: Date | undefined) => {
    if (!date) {
      setInputValue("");
      setSelectedDate(undefined);
    } else {
      setSelectedDate(date);
      setInputValue(format(date, "yyyy-MM-dd"));
      onChange(date);
    }
    dialogRef.current?.close();
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // console.log(e.target.value);
    setInputValue(e.target.value); // keep the input value in sync

    if (e.target.value.length >= 10) {
      // const parsedDate = parse(e.target.value, "yyyy-MM-dd HH:mm", new Date());
      const parsedDate = parse(e.target.value, "yyyy-MM-dd", new Date());
      // const parsedDate = dayjs(e.target.value).toDate();
      console.log(parsedDate);

      if (isValid(parsedDate)) {
        setSelectedDate(parsedDate);
        setMonth(parsedDate);
        onChange(parsedDate);
      } else {
        setSelectedDate(undefined);
        // 无效日期时保持原值
        setInputValue(inputValue);
      }
    }
  };

  React.useEffect(() => {
    if (dayjs(value).isValid()) {
      setInputValue(dayjs(value).format("YYYY-MM-DD"));
    }
  }, [value]);

  return (
    <div className={className}>
      <div className="relative flex items-center w-full">
        <Input
          style={{ fontSize: "inherit" }}
          className="pr-10 w-full"
          id="date-input"
          type="text"
          value={inputValue}
          placeholder={placeholder}
          onChange={handleInputChange}
        />{" "}
        <span
          style={{ fontSize: "inherit" }}
          className="absolute inset-y-0 right-3 flex items-center pr-3"
          onClick={toggleDialog}
          aria-controls="dialog"
          aria-haspopup="dialog"
          aria-expanded={isDialogOpen}
          aria-label="Open calendar to choose booking date"
        >
          <CalendarDays />
        </span>
      </div>
      {/* <p aria-live="assertive" aria-atomic="true">
        {selectedDate !== undefined
          ? selectedDate.toDateString()
          : "Please type or pick a date"}
      </p> */}
      <dialog
        role="dialog"
        ref={dialogRef}
        id={dialogId}
        aria-modal
        aria-labelledby={headerId}
        onClose={() => setIsDialogOpen(false)}
      >
        <DayPicker
          classNames={{
            today: `border-amber-500`, // Add a border to today's date
            selected: `bg-amber-500 border-amber-500 text-white`, // Highlight the selected day
            root: `${defaultClassNames.root} shadow-lg p-5`, // Add a shadow to the root element
            chevron: `${defaultClassNames.chevron} fill-amber-500`, // Change the color of the chevron
          }}
          {...dayPickerProps}
          // ref={ref}
          locale={zhCN}
          // captionLayout="dropdown-years"
          captionLayout="dropdown"
          showOutsideDays={true}
          month={month}
          onMonthChange={setMonth}
          numberOfMonths={1}
          mode="single" // “single" | "multiple" | "range"
          selected={selectedDate}
          onSelect={handleDayPickerSelect}
          // footer={
          //   selectedDate !== undefined &&
          //   `Selected: ${selectedDate.toDateString()}`
          // }
        />
      </dialog>
    </div>
  );
};
